home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / ease3.5 / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-12-09  |  52.8 KB

  1. Subject:  v25i019:  Ease 3.5 - high-level sendmail.cf language, Part03/06
  2. Newsgroups: comp.sources.unix
  3. Approved: vixie@pa.dec.com
  4.  
  5. Submitted-by: Bruce G. Barnett <barnett@crdgw1.ge.com>
  6. Posting-number: Volume 25, Issue 19
  7. Archive-name: ease3.5/part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 3 (of 6)."
  16. # Contents:  INTRO src/emitcf.c src/lexan.l src/main.c src/strops.c
  17. # Wrapped by vixie@cognition.pa.dec.com on Tue Dec 10 08:45:56 1991
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'INTRO' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'INTRO'\"
  21. else
  22. echo shar: Extracting \"'INTRO'\" \(7853 characters\)
  23. sed "s/^X//" >'INTRO' <<'END_OF_FILE'
  24. X        An introduction to Sendmail Rules
  25. X        Copyright 1991, All rights reserved
  26. X        Bruce Barnett
  27. X
  28. X    First of all, sendmail is easy to learn, once you learned all
  29. about electronic mail. Figuring out how to handle the address
  30. X
  31. X    bigvax::a!b!another.domain!c%d%domain.com@another.domain
  32. X
  33. is much more challenging. Here's the scoop.
  34. X
  35. X    When sendmail gets an address, it always passes it to rule 3.
  36. X
  37. X    Rule 3 with transform the address, and eventually sent it to
  38. X    rule 0.
  39. X
  40. X    Rule 0 makes the final decision, and selects three things:
  41. X
  42. X            The address
  43. X            The Machine to send the address to
  44. X            The mailer to use.
  45. X                This could be UUCP, ethernet, DECNet,
  46. X                a local user, a program, etc.
  47. X
  48. X    Once the above has been decided on, the address is transformed
  49. X    in the following way:
  50. X
  51. X    Ruleset 1 is applied to the From: line
  52. X    Ruleset 2 is applied to the To: and Cc: line
  53. X    
  54. X    Each mailer then applies a rule. These rules are other unique
  55. X    for each mailer.
  56. X
  57. X    Finally ruleset 4 is applied.
  58. X
  59. X
  60. Now let's go through an example in detail.
  61. X
  62. grymoire% /usr/lib/sendmail -bt -C/etc/sendmail.cf
  63. ADDRESS TEST MODE
  64. XEnter <ruleset> <address>
  65. X> 0 user@crdgw1.crd        # <---- I typed this line here 
  66. rewrite: ruleset  3   input: "user" "@" "crdgw1" "." "crd"
  67. rewrite: ruleset  6   input: "user" "<" "@" "crdgw1" "." "crd" ">"
  68. rewrite: ruleset  6 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
  69. rewrite: ruleset  3 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
  70. rewrite: ruleset  0   input: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
  71. rewrite: ruleset  0 returns: $# "ether" $@ "crdgw1" $: "user" "<" "@" "crdgw1" ">"
  72. X> 
  73. X
  74. Rule 3 can be given any address at all. It must determine the machine
  75. and domain which corresponds to the address. Determining the machine
  76. can be tricky, because it depends o the address. What it uses to
  77. specify the address is to surround the hostname and @ sign with angle brackets.
  78. It also added a imaginary domain to the hostname to indicate the type
  79. of network it is on. The set of angle brackets is used to "focus" on a machine.
  80. X
  81. Some typical values are:
  82. X
  83. X    < @ machine . LOCAL >     => a local host
  84. X    < @ machine >        => same as above
  85. X    < @ machine . UUCP >    => a machine on the UUCP network
  86. X
  87. The angle brackets indicate the important part - the machine and
  88. perhaps what mail agent to use. However, the username isn't included
  89. in the set of charatcers surrounded by angle brackets. The problem is,
  90. different mailers have the username in a different format. In some
  91. casess, the host is the first word, in others it's the last word.
  92. X
  93. Here is an example of an address going into rule 3 and the expected
  94. output:
  95. X
  96. X    Input        Output
  97. X    a!b!c!d!user        <@a.UUCP>!b!c!d!user    or
  98. X                b!c!d!user<@a.UUCP>
  99. X    user@a.uucp        user<@a.uucp>
  100. X    bigvax::user        user<@bigvax.DECNET>
  101. X    user%a.com@b.edu    user%a.com<@b.edu> or - it you are agressive
  102. X                user<@a.com>
  103. X    a!b!user@abc.edu    a!b!user<@abc.edu>
  104. X    @a:user@b.com        <@a>:user@b.com
  105. X    "Bruce" <barnett@local>    barnett<@local>
  106. X
  107. As you can see, the machine that will accept the message will be
  108. different depending on the address. Ruleset 3 must find the right
  109. machine, and also clean up any addresses if appropriate.
  110. It does it's work by looking for a pattern, and transforming the
  111. address when it matches the pattern. 
  112. X
  113. The cleaning up part can be confusing, but typically ruleset 3 calls
  114. other rules to do this. One rule is used to clean up addresses before
  115. the < and > are added. Another rule is used to clean up addresses
  116. after it has been converted into the < @ machine > format.
  117. X
  118. Here is the ease version of the rule that transforms a UUCP address:
  119. X
  120. X    if ( exactly_one ! one_or_more )    /* uucphost!user */
  121. X        return (RULESET_6 ($2<@$1."uucp">));
  122. X
  123. This transforms the address, but calls ruleset 6, which cleans up the
  124. addresses with < and >. The variables "exactly_one" and "one_or_more"
  125. match that number of tokens, and are replaced by the $1 or $2 on the 
  126. returned rule. ($1 is exactly_one, $2 is one_or_more).
  127. X
  128. Here is a rule in ruleset 6 that looks for an address to the local
  129. domain, and replaces the domain with "LOCAL":
  130. X
  131. X    if ( zero_or_more <@ zero_or_more  any_in_mydomainname > zero_or_more )    /* convert local domain */
  132. X        retry ($1<@$2"LOCAL">$4);
  133. X
  134. zero_or_more is a pattern, which matches $1, $2, or $4.
  135. any_in_mydomain is a special pattern that matches the domain. It is
  136. not necessary to have a $3 because the domain is known.
  137. So the test of the address user@crdgw1.crd reports this:
  138. X
  139. rewrite: ruleset  3   input: "user" "@" "crdgw1" "." "crd"
  140. rewrite: ruleset  6   input: "user" "<" "@" "crdgw1" "." "crd" ">"
  141. rewrite: ruleset  6 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
  142. rewrite: ruleset  3 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
  143. X
  144. Once ruleset 3 is down, it passes the address to 0.
  145. This eventually gets to the rule:
  146. X
  147. X/* deliver to known ethernet hosts explicitly specified in our domain */
  148. X    if ( zero_or_more <@ any_in_etc_hosts."LOCAL"> zero_or_more )    /* user@host.sun.com */
  149. X        resolve (mailer (ether),
  150. X                host ($2 ),
  151. X                user ($1<@$2>$3));
  152. X
  153. This matches, so the ether mailer is used, and the address is
  154. X$1<@2>$3, or in this case:
  155. X
  156. X
  157. rewrite: ruleset  0 returns: $# "ether" $@ "crdgw1" $: "user" "<" "@" "crdgw1" ">"
  158. X
  159. The $#, $@, and $: are sendmail talk for the mailer, machine, and
  160. address. 
  161. X
  162. Still more to come. The specificalion of the mailer is:
  163. X
  164. mailer
  165. X    ether {
  166. X        Path = "[TCP]",
  167. X        Flags = { f_mult, f_strip, f_date, f_from, f_mesg, f_upperu, f_addrw, f_dot },
  168. X        Sender = RULESET_11,
  169. X        Recipient = RULESET_21,
  170. X        Argv = "TCP ${m_rhost}"
  171. X    };
  172. X
  173. X
  174. This says the sender's address must go thru rule 11, which means rules
  175. X1, 11, and 4. The recipient's address goes through 2, 21, and 4.
  176. X
  177. To test this, type the address from ruleset 0 and specify either 1,
  178. X11, and 4 or perhaps 2, 21, and 4:
  179. X
  180. X> 1,11,4 user@crdgw1
  181. rewrite: ruleset  3   input: "user" "@" "crdgw1"
  182. rewrite: ruleset  6   input: "user" "<" "@" "crdgw1" ">"
  183. rewrite: ruleset  6 returns: "user" "<" "@" "crdgw1" ">"
  184. rewrite: ruleset  3 returns: "user" "<" "@" "crdgw1" ">"
  185. rewrite: ruleset  1   input: "user" "<" "@" "crdgw1" ">"
  186. rewrite: ruleset  1 returns: "user" "<" "@" "crdgw1" ">"
  187. rewrite: ruleset 11   input: "user" "<" "@" "crdgw1" ">"
  188. rewrite: ruleset 11 returns: "user" "<" "@" "crdgw1" ">"
  189. rewrite: ruleset  4   input: "user" "<" "@" "crdgw1" ">"
  190. rewrite: ruleset  9   input: "user" "<" "@" "crdgw1" ">"
  191. rewrite: ruleset  9 returns: "user" "<" "@" "crdgw1" ">"
  192. rewrite: ruleset  4 returns: "user" "@" "crdgw1"
  193. X
  194. As you can see, ruleset 3 is always applied first, which calls 6, 
  195. Then rule 1 is applied, followed by rule 11, and then followed by
  196. rule 4. The end result tells me the From: line would look like
  197. user@crdgw1
  198. X
  199. X
  200. The uucp mailer has a diffent set of rewrite rules.
  201. In sun's sendmail.main.cf, it uses 13 and 23. To test this address,
  202. I typed 1,13,4 and got this:
  203. X
  204. X> 1,13,4 user@crdgw1
  205. rewrite: ruleset  3   input: "user" "@" "crdgw1"
  206. rewrite: ruleset  6   input: "user" "<" "@" "crdgw1" ">"
  207. rewrite: ruleset  6 returns: "user" "<" "@" "crdgw1" ">"
  208. rewrite: ruleset  3 returns: "user" "<" "@" "crdgw1" ">"
  209. rewrite: ruleset  1   input: "user" "<" "@" "crdgw1" ">"
  210. rewrite: ruleset  1 returns: "user" "<" "@" "crdgw1" ">"
  211. rewrite: ruleset 13   input: "user" "<" "@" "crdgw1" ">"
  212. rewrite: ruleset  5   input: "user" "<" "@" "crdgw1" ">"
  213. rewrite: ruleset  5 returns: "crdgw1" "!" "user"
  214. rewrite: ruleset 13 returns: "grymoire" "!" "crdgw1" "!" "user"
  215. rewrite: ruleset  4   input: "grymoire" "!" "crdgw1" "!" "user"
  216. rewrite: ruleset  9   input: "grymoire" "!" "crdgw1" "!" "user"
  217. rewrite: ruleset  9 returns: "grymoire" "!" "crdgw1" "!" "user"
  218. rewrite: ruleset  4 returns: "grymoire" "!" "crdgw1" "!" "user"
  219. X> 
  220. X
  221. As you can see, it converted the address into a uucp path relative to
  222. my machine.
  223. X
  224. To test these three cases, add the following to your debug.in file:
  225. X
  226. X0    user@crdgw1
  227. X1,11,4    user@crdgw1    From_Ethernet_to_Ethernet
  228. X1,13,4    user@crdgw1    From_Ethernet_to_UUCP
  229. X
  230. END_OF_FILE
  231. if test 7853 -ne `wc -c <'INTRO'`; then
  232.     echo shar: \"'INTRO'\" unpacked with wrong size!
  233. fi
  234. # end of 'INTRO'
  235. fi
  236. if test -f 'src/emitcf.c' -a "${1}" != "-c" ; then 
  237.   echo shar: Will not clobber existing file \"'src/emitcf.c'\"
  238. else
  239. echo shar: Extracting \"'src/emitcf.c'\" \(7842 characters\)
  240. sed "s/^X//" >'src/emitcf.c' <<'END_OF_FILE'
  241. X#ifdef FLUKE
  242. X# ifndef LINT
  243. X    static char RCSid[] = "@(#)FLUKE  $Header: /home/kreskin/u0/barnett/Src/Ease/ease/src/RCS/emitcf.c,v 3.0 1991/02/22 18:50:27 barnett Exp $";
  244. X# endif LINT
  245. X#endif FLUKE
  246. X
  247. X/*
  248. X *    emitcf.c  -- This file contains routines associated with the writing
  249. X *             and formatting of a translated sendmail configuration file.
  250. X *
  251. X *    author      -- James S. Schoner, Purdue University Computing Center,
  252. X *                         West Lafayette, Indiana  47907
  253. X *
  254. X *      date      -- July 9, 1985
  255. X *
  256. X *    Copyright (c) 1985 by Purdue Research Foundation
  257. X *
  258. X *    All rights reserved.
  259. X *
  260. X * $Log: emitcf.c,v $
  261. X * Revision 3.0  1991/02/22  18:50:27  barnett
  262. X * Added support for HP/UX and IDA sendmail.
  263. X *
  264. X * Revision 2.1  1990/01/30  14:09:49  jeff
  265. X * Changes by Bruce Barnett - extensions for SunOS/Ultrix.
  266. X *
  267. X * Revision 2.0  88/06/15  14:40:47  root
  268. X * Baseline release for net posting. ADR.
  269. X */
  270. X
  271. X#include <stdio.h>
  272. X#include "symtab.h"
  273. X#include "fixstrings.h"
  274. X
  275. X#define REGLINE 60    /* length of output lines which may be continued */
  276. X#define MAXLINE 256    /* liberal maximum line length             */
  277. X
  278. extern short Rformat;            /* read-format flag for a class  */
  279. extern char *MacScan ();
  280. extern char  MakeMac ();
  281. extern void  PrintError (),
  282. X         FatalError (),
  283. X         PrintWarning (),
  284. X         ErrorReport ();
  285. X
  286. void  PrintDef ();
  287. X
  288. static char ClassCH;            /* printable class macro char    */
  289. X
  290. X/*
  291. X *    EmitDef () -- Emit a definition line (Ease block definition) in cf 
  292. X *              format.
  293. X *
  294. X */
  295. void
  296. XEmitDef (blockdef, targ, defstr1, defstr2)
  297. register enum bdefs blockdef;    /* type of definition        */
  298. register struct he *targ;    /* target to be defined      */
  299. char *defstr1, *defstr2;    /* one or two definition strings */
  300. X{
  301. X    /*
  302. X     *  This routine is about as pretty as a translated ease file...
  303. X     *  Each type of line (Ease block) is handled case by case below.
  304. X     *
  305. X     */
  306. X    switch (blockdef) {
  307. X        case def_macro:        printf ("D%c", MakeMac (targ, ID_MACRO));
  308. X                    PrintDef (def_macro, MacScan (defstr1));
  309. X                    if (ISMACRO(targ->idd))
  310. X                        PrintWarning ("Redefining macro %s.\n", targ->psb);
  311. X                    targ->idd |= ID_MACRO;  /* signal definition */
  312. X                    break;
  313. X
  314. X        case def_class:        if (Rformat)    /* read format */
  315. X                        printf ("F");
  316. X                    else
  317. X                        printf ("C");
  318. X                    printf ("%c", ClassCH = MakeMac (targ, ID_CLASS));
  319. X                    if (Rformat) {    /* read format */
  320. X                        printf ("%s\n", defstr1);
  321. X                        Rformat = FALSE;
  322. X                    } else
  323. X                        PrintDef (def_class, MacScan(defstr1));
  324. X                    if (ISCLASS(targ->idd))
  325. X                        PrintWarning ("Appending to previously defined class %s.\n", targ->psb);
  326. X                    targ->idd |= ID_CLASS;  /* signal definition */
  327. X                    break;
  328. X
  329. X        case def_option:    if (defstr1 == NULL)
  330. X                        FatalError ("No option passed in EmitDef()", (char *)NULL);
  331. X                    printf ("O%c", *defstr1);
  332. X                    PrintDef (def_option, defstr2);
  333. X                    break;
  334. X
  335. X        case def_prec:        printf ("P%s=%d\n", targ->psb, targ->idval.prec);
  336. X                    break;
  337. X
  338. X        case def_trusted:    printf ("T");
  339. X                    PrintDef (def_trusted, defstr1);
  340. X                    break;
  341. X
  342. X        case def_header:    printf ("H");
  343. X                    if (defstr1 != NULL)
  344. X                        printf ("?%s?", defstr1);
  345. X                    PrintDef (def_header, defstr2);
  346. X                    break;
  347. X
  348. X        case def_mailer:    if (ISMAILER(targ->idtype)) {
  349. X                        if (ISMAILER(targ->idd))
  350. X                            PrintWarning ("Redefining mailer %s.\n", targ->psb);
  351. X                    } else if (ISTYPED(targ->idtype)) {
  352. X                        PrintError ("Redeclaration of identifier as mailer: %s", targ->psb);
  353. X                        return;
  354. X                    }
  355. X                    targ->idd |= ID_MAILER;  /* signal definition */
  356. X                    printf ("M%s, ", targ->psb);
  357. X                    PrintDef (def_mailer, defstr1);
  358. X                    break;
  359. X
  360. X        case def_ruleset:    printf ("R");
  361. X                    PrintDef (def_ruleset, defstr1);
  362. X                    break;
  363. X
  364. X        default:        FatalError ("Bad case in EmitDef ()", (char *) NULL);
  365. X    }
  366. X}
  367. X
  368. X
  369. X/*
  370. X *      PrintContinued () -- Print a line definition (buf) by splitting it over
  371. X *                 more than one line.  The two definition types 
  372. X *                 accepted for this method of continuation are class
  373. X *                 and trusted user lists, indicated in the argument 
  374. X *                 btype 
  375. X *
  376. X */
  377. void
  378. PrintContinued (btype, buf)
  379. enum bdefs     btype;    /* block (line) type for definition */
  380. register char *buf;    /* buffer containing the definition */
  381. X{
  382. X    register char *tmp;    /* breakpoint search pointer   */
  383. X    register char  tc;    /* temporary swap byte         */
  384. X    int  buflen;        /* length of definition buffer */    
  385. X
  386. X    buflen = strlen (buf);
  387. X    tmp = buf + REGLINE;
  388. X    while ((*--tmp != ' ') && (tmp != buf))     /* look for suitable break */
  389. X        /* null */ ;
  390. X    if (tmp == buf) {
  391. X        for (tmp = buf + REGLINE; (*tmp != ' ') && (tmp - buf != buflen); tmp++)
  392. X            /* null */ ;
  393. X        if ((tmp - buf) >= MAXLINE)
  394. X            PrintWarning ("Member name may be too long.\n", (char *) NULL);
  395. X    }
  396. X    tc = *tmp;        /* swap break char with null char */
  397. X    *tmp = '\0';
  398. X    printf ("%s\n", buf);
  399. X    if ((*tmp = tc) == '\0')
  400. X        return;
  401. X    else
  402. X        tmp++;
  403. X    if (btype == def_class)        /* start next line   */
  404. X        printf ("C%c", ClassCH);
  405. X    else
  406. X        printf ("T");
  407. X    if (strlen (tmp) < REGLINE)    /* continue the line */
  408. X        printf ("%s\n", tmp);
  409. X    else
  410. X        PrintContinued (btype, tmp);
  411. X}
  412. X
  413. X
  414. X/*
  415. X *    PrintDef () -- Handles special cases (like line continuation) when 
  416. X *               printing definitions.
  417. X *
  418. X */
  419. void
  420. PrintDef (btype, dstr)
  421. register enum bdefs btype;    /* block type (output line type) */
  422. register char *dstr;        /* definition string         */
  423. X{
  424. X    register char *tmp;
  425. X
  426. X    if (dstr == (char *)NULL)
  427. X        dstr = "";
  428. X
  429. X    for (tmp = dstr; *tmp != '\0'; tmp++)     /* search for line continuations */
  430. X        if ((*tmp == '\\') && (*++tmp == '\n'))
  431. X            if (btype != def_header) {
  432. X                ErrorReport ("Non-header string contains line continuation\n");
  433. X                return;
  434. X            } else
  435. X                break;
  436. X
  437. X    /*
  438. X     *  Perform case by case handling of definition printing.
  439. X     *
  440. X     */
  441. X    switch (btype) {
  442. X        case def_header :  if (*tmp-- == '\n') {
  443. X                    *tmp = '\0';
  444. X                    if (tmp - dstr >= MAXLINE)
  445. X                        PrintWarning ("Header may be too long.\n", 
  446. X                                  (char *) NULL);
  447. X                    printf ("%s\n\t", dstr);
  448. X                    tmp += 2;
  449. X                        PrintDef (def_header, tmp);
  450. X                   } else {
  451. X                    if (strlen (dstr) >= MAXLINE)
  452. X                        PrintWarning ("Header may be too long.\n", 
  453. X                                  (char *) NULL);
  454. X                    printf ("%s\n", dstr);
  455. X                   }
  456. X                   break;
  457. X
  458. X        case def_mailer :  if (strlen (dstr) >= MAXLINE)
  459. X                    PrintWarning ("Mailer definition may be too long.\n", 
  460. X                              (char *) NULL);
  461. X                   printf ("%s\n", dstr);
  462. X                   break;
  463. X
  464. X        case def_ruleset:  if (strlen (dstr) >= MAXLINE)
  465. X                    PrintWarning ("Rewriting rule may be too long.\n", 
  466. X                              (char *) NULL);
  467. X                   printf ("%s\n", dstr);
  468. X                   break;
  469. X
  470. X        case def_option :  if (strlen (dstr) >= MAXLINE)
  471. X                    PrintWarning ("Option assignment may be too long.\n", 
  472. X                              (char *) NULL);
  473. X                   printf ("%s\n", dstr);
  474. X                   break;
  475. X
  476. X        case def_macro  :  if (strlen (dstr) >= MAXLINE)
  477. X                    PrintWarning ("Macro assignment may be too long.\n", 
  478. X                              (char *) NULL);
  479. X                   printf ("%s\n", dstr);
  480. X                   break;
  481. X
  482. X        case def_prec   :  if (strlen (dstr) >= MAXLINE)
  483. X                    PrintWarning ("Precedence relation may be too long.\n", 
  484. X                              (char *) NULL);
  485. X                   printf ("%s\n", dstr);
  486. X                   break;
  487. X
  488. X        case def_trusted:
  489. X        case def_class  :  if (strlen (dstr) < REGLINE)
  490. X                    printf ("%s\n", dstr);
  491. X                   else        /* use line continuation feature */
  492. X                       PrintContinued (btype, dstr);
  493. X                   break;
  494. X
  495. X        default         :  FatalError ("Invalid case in PrintDef ()", (char *) NULL);
  496. X    }
  497. X}
  498. X
  499. X
  500. X/*
  501. X *    StartRuleset () -- Prints a ruleset heading for the ruleset identifier
  502. X *                   contained in the argument rsid.
  503. X *
  504. X */
  505. void
  506. StartRuleset (rsid)
  507. register struct he *rsid;    /* ruleset identifier */
  508. X{
  509. X    if (!ISRULESET(rsid->idtype))
  510. X        if (ISTYPED(rsid->idtype))
  511. X            PrintError ("Identifier not of ruleset type: %s", rsid->psb);
  512. X        else
  513. X            PrintError ("Ruleset identifier not bound to a number: %s", rsid->psb);
  514. X    else {
  515. X        if (ISRULESET(rsid->idd))
  516. X            PrintWarning ("Redefining ruleset %s.\n", rsid->psb);
  517. X        rsid->idd |= ID_RULESET;
  518. X        printf ("S%s\n", rsid->idval.rsn);
  519. X    }
  520. X}
  521. END_OF_FILE
  522. if test 7842 -ne `wc -c <'src/emitcf.c'`; then
  523.     echo shar: \"'src/emitcf.c'\" unpacked with wrong size!
  524. fi
  525. # end of 'src/emitcf.c'
  526. fi
  527. if test -f 'src/lexan.l' -a "${1}" != "-c" ; then 
  528.   echo shar: Will not clobber existing file \"'src/lexan.l'\"
  529. else
  530. echo shar: Extracting \"'src/lexan.l'\" \(8822 characters\)
  531. sed "s/^X//" >'src/lexan.l' <<'END_OF_FILE'
  532. X%{
  533. X
  534. X#ifdef FLUKE
  535. X# ifndef LINT
  536. X    static char RCSid[] = "@(#)FLUKE  $Header: /home/kreskin/u0/barnett/Src/ease/src/RCS/lexan.l,v 3.2 1991/05/16 10:45:25 barnett Exp $";
  537. X# endif LINT
  538. X#endif FLUKE
  539. X
  540. X/*
  541. X *    lexan.l -- Lexical Analyzer for EASE.
  542. X *
  543. X *           Contains code for lex(1) which generates a lexical
  544. X *           analyzer (lex.yy.c) for Ease, a high-level specification 
  545. X *           format for sendmail configuration files.
  546. X *
  547. X *    author -- James S. Schoner, Purdue University Computing Center,
  548. X *                    West Lafayette, Indiana  47907
  549. X *
  550. X *    date   -- July 1, 1985
  551. X *
  552. X *    Copyright (c) 1985 by Purdue Research Foundation
  553. X *
  554. X *    All rights reserved.
  555. X *
  556. X * $Log: lexan.l,v $
  557. X * Revision 3.2  1991/05/16  10:45:25  barnett
  558. X * Better support for System V machines
  559. X * Support for machines with read only text segments
  560. X *
  561. X * Revision 3.1  1991/02/25  22:09:52  barnett
  562. X * Fixed some portability problems
  563. X *
  564. X * Revision 3.0  1991/02/22  18:50:27  barnett
  565. X * Added support for HP/UX and IDA sendmail.
  566. X *
  567. X * Revision 2.3  1991/02/12  20:49:34  barnett
  568. X * Added several new tokens.
  569. X * Merged Jeff's changes with my own.
  570. X *
  571. X * Revision 2.2  1990/05/07  11:12:53  jeff
  572. X * Add support for the "Cflag" variable which controls whether or not
  573. X * input lines are passed through as comments in the output stream.
  574. X *
  575. X * Version 2.1  90/01/30  15:26:23  jeff
  576. X * If -C flag is specified, emit input as comments in the output stream.
  577. X * 
  578. X * Revision 2.0  88/06/15  15:11:30  root
  579. X * Baseline release for net posting. ADR.
  580. X * 
  581. X */
  582. X
  583. X#include "fixstrings.h"
  584. X#include "symtab.h"
  585. X#include "lexdefs.h"
  586. X
  587. X#define  LEXnewline '\n'
  588. X#define     LEXeof        '\0'
  589. X#define  MaxFN        200            /* maximum file name length */
  590. X
  591. extern int      EchoInputAsComments;
  592. extern struct he *LookupSymbol ();
  593. extern void      ErrorReport ();
  594. extern void      yymark();
  595. extern void      PrintError();
  596. extern char *      malloc ();
  597. X
  598. int  Lcount;                /* line counter            */
  599. char FNbuf[MaxFN];            /* file name buffer        */
  600. short RMatch  = FALSE;            /* ruleset match flag          */
  601. X
  602. X#ifdef YYDEBUG
  603. extern int yychar;
  604. X#else
  605. int   yychar;
  606. X#endif
  607. X
  608. X#undef input
  609. X# define input() (((yytchar=yychar=yysptr>yysbuf?U(*--yysptr):Getc(yyin,yyout))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
  610. X
  611. int
  612. Getc (yyin, yyout)
  613. X    FILE *yyin, *yyout;
  614. X{
  615. X    static char linbuf[BUFSIZ], *pc = linbuf;
  616. X    char c;
  617. X
  618. X    /* initialize buffer: first call only */
  619. X    if (*pc == '\0' && pc == linbuf) {
  620. X        if (fgets(linbuf, BUFSIZ, yyin)==NULL)
  621. X            return EOF;
  622. X        /* echo input as comment */
  623. X        if (EchoInputAsComments) {
  624. X            fprintf(yyout, "%s%s", (linbuf[0] == '#' ? "" : "# "), linbuf);
  625. X        }
  626. X    }
  627. X    c = *pc++;
  628. X    if (c == '\n') {
  629. X        pc = linbuf;
  630. X        if (fgets(linbuf, BUFSIZ, yyin) == NULL)
  631. X            *pc = (char) EOF;
  632. X        else
  633. X            /* echo input as comment (except cpp comments) */
  634. X            if (EchoInputAsComments) {
  635. X                fprintf(yyout, "%s%s",
  636. X                (linbuf[0] == '#' ? "" : "# "), linbuf);
  637. X            }
  638. X    }
  639. X     return (c == (char) EOF) ? EOF : c;
  640. X}
  641. X
  642. X/*
  643. X * Table of keywords. NOTE: This is in sorted order, and
  644. X * must stay that way if anything else is added to it.
  645. X */
  646. static struct resword {
  647. X    char    *r_text;
  648. X    int    r_tokval;
  649. X} reswords[] = {
  650. X    { "Argv",        MARGV },
  651. X    { "Eol",        MEOL },
  652. X    { "Flags",        MFLAGS },
  653. X    { "Maxsize",        MMAXSIZE },
  654. X    { "Path",        MPATH },
  655. X    { "Recipient",        MRECIPIENT },
  656. X    { "Sender",        MSENDER },
  657. X     { "alias",        ALIAS },
  658. X     { "asm",        ASM },
  659. X    { "bind",        BIND },
  660. X    { "canon",        CANON },
  661. X    { "class",        CLASS },
  662. X    { "concat",        CONCAT },
  663. X    { "d_background",    DOPTB },
  664. X    { "d_interactive",    DOPTI },
  665. X    { "d_queue",        DOPTQ },
  666. X    { "dbm",        DBM },       /* IDA */
  667. X    { "default",        DEFAULT }, /* IDA */
  668. X    { "define",        DEFINE },
  669. X     { "eval",        EVAL },
  670. X    { "f_addrw",        CCFLAG },
  671. X    { "f_arpa",        AAFLAG },
  672. X     { "f_bsmtp",        BBFLAG },    /* IDA */
  673. X    { "f_date",        DDFLAG },
  674. X    { "f_dot",        XXFLAG },
  675. X    { "f_escape",        EEFLAG },
  676. X    { "f_expensive",    EFLAG },
  677. X    { "f_ffrom",        FFLAG },
  678. X    { "f_from",        FFFLAG },
  679. X    { "f_full",        XFLAG },
  680. X    { "f_llimit",        LLFLAG },
  681. X    { "f_locm",        LFLAG },
  682. X    { "f_mail11",        HHFLAG },  /* Ultrix */
  683. X    { "f_mesg",        MMFLAG },
  684. X    { "f_mult",        MFLAG },
  685. X    { "f_noreset",        SSFLAG },
  686. X    { "f_noufrom",        NFLAG },
  687. X     { "f_relativize",    VVFLAG },    /* IDA */
  688. X    { "f_retsmtp",        PFLAG },
  689. X    { "f_return",        PPFLAG },
  690. X    { "f_rfrom",        RFLAG },
  691. X    { "f_rport",        RRFLAG },
  692. X    { "f_smtp",        IIFLAG },
  693. X    { "f_strip",        SFLAG },
  694. X    { "f_ufrom",        UUFLAG },
  695. X    { "f_upperh",        HFLAG },
  696. X    { "f_upperu",        UFLAG },
  697. X    { "field",        FIELD },
  698. X    { "for",        FOR },
  699. X    { "h_exit",        EOPTE },
  700. X    { "h_mail",        EOPTM },
  701. X    { "h_mailz",        EOPTZ },
  702. X    { "h_print",        EOPTP },
  703. X    { "h_write",        EOPTW },
  704. X    { "header",        HEADER },
  705. X    { "host",        HOST },
  706. X    { "hostnum",        HOSTNUM },
  707. X    { "if",            IF },
  708. X    { "ifset",        IFSET },
  709. X    { "in",            IN },
  710. X    { "macro",        MACRO },
  711. X    { "mailer",        MAILER },
  712. X    { "map",        MAP },
  713. X    { "match",        MATCH },
  714. X    { "next",        NEXT },
  715. X    { "o_alias",        AAOPT },
  716. X     { "o_aliasfile",    YYOPT },    /* SunOS */
  717. X    { "o_bsub",        BBOPT },
  718. X    { "o_checkpoint",    CCOPT },
  719. X    { "o_delivery",        DOPT },
  720. X    { "o_dmuid",        UOPT },
  721. X    { "o_dnet",        NNOPT },
  722. X     { "o_envelope",        SLOPT },    /* IDA */
  723. X    { "o_ewait",        AOPT },
  724. X    { "o_flog",        SSOPT },
  725. X    { "o_fsmtp",        HHOPT },
  726. X    { "o_gid",        GOPT },
  727. X    { "o_handling",        EOPT },
  728. X    { "o_hformat",        OOPT },
  729. X    { "o_loadnc",        XXOPT },
  730. X    { "o_loadq",        XOPT },
  731. X    { "o_maxempty",        BOPT },    /* SunOS */
  732. X     { "o_maxhops",        HOPT }, /* SunOS */
  733. X      { "o_nameserver",    IIOPT }, /* HP/UX */
  734. X      { "o_newproc",        YYOPT },
  735. X     { "o_nfs",        RROPT },    /* SunOS 4.0 */
  736. X    { "o_pmaster",        PPOPT },
  737. X    { "o_prifactor",    ZOPT },
  738. X    { "o_qdir",        QQOPT },
  739. X    { "o_qfactor",        QOPT },
  740. X    { "o_qtimeout",        TTOPT },
  741. X    { "o_qwait",        COPT },
  742. X    { "o_rebuild",        DDOPT },
  743. X    { "o_recipfactor",    YOPT },
  744. X    { "o_rsend",        MOPT },
  745. X    { "o_safe",        SOPT },
  746. X    { "o_skipd",        IOPT },
  747. X    { "o_slog",        LLOPT },
  748. X    { "o_timezone",        TOPT },
  749. X    { "o_tmode",        FFOPT },
  750. X    { "o_tread",        ROPT },
  751. X    { "o_usave",        FOPT },
  752. X    { "o_validate",        NOPT },
  753. X    { "o_verbose",        VOPT },
  754. X    { "o_waitfactor",    ZZOPT },
  755. X    { "o_wizpass",        WWOPT },
  756. X    { "options",        OPTIONS },
  757. X    { "precedence",        PRECEDENCE },
  758. X     { "program",        PROGRAM },    /* HP/UX */
  759. X     { "quote",        QUOTE },
  760. X    { "readclass",        READCLASS },
  761. X    { "resolve",        RESOLVE },
  762. X     { "resolved",        RESOLVED },
  763. X    { "retry",        RETRY },
  764. X    { "return",        RETURN },
  765. X    { "ruleset",        RULESET },
  766. X    { "trusted",        TRUSTED },
  767. X    { "user",        USER },
  768. X    { "while",        IF },
  769. X     { "ypalias",        YPALIAS },    /* Ultrix */
  770. X     { "ypmap",        YPMAP },    /* SunOS */
  771. X     { "yppasswd",        YPPASSWD },    /* Ultrix */
  772. X};
  773. X%}
  774. X
  775. X%%
  776. X    int INch;            /* any input character */
  777. X
  778. X[ \t\f]+            ;     /* discard whitepsace  */
  779. X[\n]                Lcount++;
  780. X^\#[ \t]*[0-9]+[ \t]*\".*\"[ \t]*.*[\n]    {
  781. X/*                    sscanf (yytext, "%*c%d%s", &Lcount, FNbuf); */
  782. X                            yymark();
  783. X                    }
  784. X[A-Za-z_][A-Za-z0-9_-]*        {
  785. X                register int l, h, m, r, c;
  786. X
  787. X                l = 0;
  788. X                h = (sizeof (reswords) / sizeof(reswords[0])) - 1;
  789. X                while (l <= h) {
  790. X                    m = (h + l) / 2;
  791. X                    c = yytext[0] - reswords[m].r_text[0];
  792. X                    r = c ? c : strcmp (yytext, reswords[m].r_text);
  793. X                    if (r < 0)
  794. X                        h = m - 1;
  795. X                    else if (r > 0)
  796. X                        l = m + 1;
  797. X                    else
  798. X                        return reswords[m].r_tokval;
  799. X                }
  800. X
  801. X                /* not a keyword */
  802. X
  803. X                /* store identifiers in symbol table */
  804. X                yylval.phe = LookupSymbol (yytext);
  805. X                return (IDENT);
  806. X                }
  807. X["]((\\\n)|(\\\")|[^"\n])*    {
  808. X                if ((INch = input()) == LEXnewline) {
  809. X                    ErrorReport ("End of line in string.\n");
  810. X                    unput (INch);
  811. X                }
  812. X                fixquotes ();
  813. X                yylval.psb = (char *) malloc (strlen (yytext) + 1);
  814. X                strcpy (yylval.psb, yytext + 1);
  815. X                return (SCONST);
  816. X                }
  817. X[0][0-7]*            {
  818. X                sscanf (yytext, "%o", &yylval.ival);  /* octal constant */
  819. X                return (ICONST);
  820. X                }
  821. X[-]?[1-9][0-9]*            {
  822. X                yylval.ival = atoi (yytext);
  823. X                return (ICONST);
  824. X                }
  825. X"="                return (ASGN);
  826. X","                return (COMMA);
  827. X"{"                return (LBRACE);
  828. X"}"                return (RBRACE);
  829. X"("                return (LPAREN);
  830. X")"                return (RPAREN);
  831. X";"                return (SEMI);
  832. X"$"                return (DOLLAR);
  833. X":"                return (COLON);
  834. X"*"                return (STAR);
  835. X"/*"                {
  836. X                /* eat C comments */
  837. X                INch = input ();
  838. X                while ((INch != '*') || 
  839. X                      ((INch = input ()) != '/')) {
  840. X                    if (INch == LEXnewline)
  841. X                        Lcount++;
  842. X                    else
  843. X                        if (INch == LEXeof) {
  844. X                            ErrorReport ("End of file in comment.\n");
  845. X                            break;
  846. X                        }
  847. X                    if (INch != '*')
  848. X                        INch = input ();
  849. X                }
  850. X                }
  851. X"/"                return (SLASH);
  852. X[\\]?.                {
  853. X                if (RMatch) {    /* in rulesets, return literal character */
  854. X                    yylval.ival = (yytext[0] == '\\') ? yytext[1] : yytext[0];
  855. X                    return (SEPCHAR);
  856. X                } else {
  857. X                    PrintError ("Illegal delimiter character: (octal code) \\%03o", *yytext);
  858. X                }
  859. X                }
  860. X%%
  861. X
  862. X/*
  863. X * fixquotes --- inside a "quoted string", turn `\"' into just `"'
  864. X *
  865. X * this is most useful inside the Argv strings for mailers,
  866. X * particularly when debugging.
  867. X */
  868. X
  869. fixquotes ()
  870. X{
  871. X    register char *cp1, *cp2;
  872. X
  873. X    cp1 = cp2 = yytext;
  874. X    while (*cp2) {
  875. X        /*
  876. X         * if we really wanted to get fancy,
  877. X         * at this point we'd handle C escapes,
  878. X         * but I don't think it's necessary.
  879. X         */
  880. X        if (*cp2 == '\\' && cp2[1] == '"')
  881. X            cp2++;
  882. X        *cp1++ = *cp2++;
  883. X    }
  884. X    *cp1++ = *cp2++;    /* final '\0' */
  885. X}
  886. END_OF_FILE
  887. if test 8822 -ne `wc -c <'src/lexan.l'`; then
  888.     echo shar: \"'src/lexan.l'\" unpacked with wrong size!
  889. fi
  890. # end of 'src/lexan.l'
  891. fi
  892. if test -f 'src/main.c' -a "${1}" != "-c" ; then 
  893.   echo shar: Will not clobber existing file \"'src/main.c'\"
  894. else
  895. echo shar: Extracting \"'src/main.c'\" \(7952 characters\)
  896. sed "s/^X//" >'src/main.c' <<'END_OF_FILE'
  897. X#ifdef FLUKE
  898. X# ifndef LINT
  899. X    static char RCSid[] = "@(#)FLUKE  $Header: /home/kreskin/u0/barnett/Src/ease/src/RCS/main.c,v 3.2 1991/05/16 10:45:25 barnett Exp $";
  900. X# endif LINT
  901. X#endif FLUKE
  902. X
  903. X/*
  904. X *      main.c     -- Main procedure for Ease Translator.
  905. X *
  906. X *      author     -- James S. Schoner, Purdue University Computing Center
  907. X *                        West Lafayette, Indiana  47907
  908. X *
  909. X *      date       -- July 9, 1985
  910. X *
  911. X *    Copyright (c) 1985 by Purdue Research Foundation
  912. X *
  913. X *    All rights reserved.
  914. X *
  915. X * $Log: main.c,v $
  916. X * Revision 3.2  1991/05/16  10:45:25  barnett
  917. X * Better support for System V machines
  918. X * Support for machines with read only text segments
  919. X *
  920. X * Revision 3.1  1991/02/25  22:09:52  barnett
  921. X * Fixed some portability problems
  922. X *
  923. X * Revision 2.2  1990/05/07  11:14:02  jeff
  924. X * Add support for the "-q" flag which controls whether input lines
  925. X * are passed through as comments in the output stream.
  926. X *
  927. X * Version 2.1  90/01/30  15:37:16  jeff
  928. X * Filter input file through cpp before processing it.
  929. X * 
  930. X * Revision 2.0  88/06/15  14:42:41  root
  931. X * Baseline release for net posting. ADR.
  932. X * 
  933. X */
  934. X
  935. X
  936. X#ifndef CPP    /* filename of preprocessor */
  937. X#    define CPP    "/lib/cpp"
  938. X#endif    CPP
  939. X
  940. X#ifndef CPPARGS        /* valid arguments  of preprocessor */
  941. X#ifdef sun        /* Sun's cpp has more options - I guess */
  942. X#    define CPPARGS    "BCHpPRTDIUY"
  943. X#else
  944. X#    define CPPARGS    "CDEIPU"
  945. X#endif sun
  946. X#endif    CPP
  947. X
  948. X#include "fixstrings.h"
  949. X#include <stdio.h>
  950. X#include <ctype.h>
  951. X#ifdef SYSV
  952. X#define index strchr
  953. X#define rindex strrchr
  954. X#endif
  955. X#ifdef MALLOC_DEBUG
  956. extern int malloc_debug();
  957. extern int malloc_verify();
  958. X#endif /* MALLOC_DEBUG */
  959. X
  960. extern FILE *DIAGf;            /* diagnostic file */
  961. char *infile = 0;            /* input file name */
  962. char *outfile = 0;            /* output file name */
  963. extern void InitError (), 
  964. X#ifndef    DATA_RW
  965. X        InitStrOps (),
  966. X        InitParser (),
  967. X#endif
  968. X        InitSymbolTable (),
  969. X        DefScan (),
  970. X        FatalError (),
  971. X            PreLoad ();
  972. X
  973. int EchoInputAsComments = 1;        /* should input lines be echoed
  974. X                     * as comments?
  975. X                     */
  976. int ErrorCount;                /* translation error count */
  977. void GetArgs ();            /* gets arguments to "et"  */
  978. X
  979. X#ifdef YYDEBUG
  980. extern int yydebug;
  981. X#else
  982. static int yydebug;
  983. X#endif
  984. X
  985. X/*
  986. X *    main () -- Main procedure for the Ease Translator et.  If no files are 
  987. X *                  given as arguments to et, stdin is translated and written to 
  988. X *               stdout.  If one file is given, it is translated and written 
  989. X *               to stdout.  If two files are given, the first is translated
  990. X *               and written to the second.  If the first filename is "-",
  991. X *               standard input is assumed.  A translation is performed on 
  992. X *               valid Ease input only, producing a regular sendmail 
  993. X *           configuration file. 
  994. X *
  995. X */
  996. void
  997. main (argc, argv)
  998. int argc;        /* argument count for "et"  */
  999. char *argv[];        /* argument vector for "et" */
  1000. X{
  1001. X#ifdef MALLOC_DEBUG
  1002. X        malloc_debug(1);
  1003. X#endif MALLOC_DEBUG
  1004. X    InitError ();            /* initialize error conditions */
  1005. X#ifndef    DATA_RW
  1006. X    InitParser ();
  1007. X    InitStrOps();
  1008. X    
  1009. X#endif
  1010. X    InitSymbolTable ();        /* initialize the symbol table */
  1011. X    PreLoad ();            /* preload special identifiers */
  1012. X    GetArgs (argc, argv);        /* set up argument files       */
  1013. X    (void) yyparse ();        /* perform translation           */
  1014. X    if (fflush (stdout) == EOF)
  1015. X        FatalError ("Cannot flush output stream/file", (char *) NULL);
  1016. X    DefScan ();                /* warn about undefined idents */
  1017. X    if (ErrorCount)
  1018. X        fprintf (DIAGf, "\n\n*** %d error(s) detected.\n", ErrorCount);
  1019. X    exit (ErrorCount);
  1020. X}
  1021. X
  1022. X
  1023. X/*
  1024. X *    GetArgs () -- Processes arguments to the Ease translator "et".  The
  1025. X *              arguments are files (margv) which may replace either/both
  1026. X *              of the files standard input and standard output.  The 
  1027. X *              following cases are possible:
  1028. X *            
  1029. X *              -- et f.e f.cf
  1030. X *                Translate Ease file f.e and write result
  1031. X *                to f.cf.
  1032. X *
  1033. X *              -- et f.e
  1034. X *                Translate Ease file f.e and write result to
  1035. X *                standard output.
  1036. X *
  1037. X *              -- et - f.cf
  1038. X *                Translate standard input and write result to
  1039. X *                f.cf.
  1040. X *
  1041. X *              -- et
  1042. X *                Translate standard input and write result to
  1043. X *                standard output.
  1044. X *
  1045. X *              et also accepts arguments. These include the /lib/cpp arguments
  1046. X *              and the -d argument for debugging grammars.
  1047. X *
  1048. X *              Finally, a message indicating the volatility of the 
  1049. X *              Ease output is written.
  1050. X *
  1051. X */
  1052. void
  1053. GetArgs (margc, margv)
  1054. register int   margc;        /* argument count  */
  1055. register char **margv;        /* argument vector */
  1056. X{
  1057. X     int    cppflags = 0;
  1058. X     int    otherflags = 0;
  1059. X     int arg;
  1060. X     for (arg = 1; arg < margc; ++arg) {        /* scan arguments */
  1061. X     if (margv[arg][0] == '-') {        /* a flag?*/
  1062. X         if (isalpha(margv[arg][1])) {    /* yes - a flag */
  1063. X         if (index(CPPARGS,margv[arg][1])) ++cppflags;    /* one belonging to the CPP */
  1064. X         else if (margv[arg][1] == 'd' ) yydebug = 1;
  1065. X         else if (margv[arg][1] == 'q' ) EchoInputAsComments = 0;
  1066. X         else ++otherflags;
  1067. X         } else if (! margv[arg][1]) {     /* this argument is just a '-' */
  1068. X         if ( (arg - yydebug - cppflags - otherflags) == 1 )
  1069. X           infile = margv[arg];    
  1070. X         else if ( (arg - yydebug - cppflags - otherflags) == 2 )
  1071. X           outfile = margv[arg];
  1072. X         else
  1073. X           FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
  1074. X         } else {
  1075. X         FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
  1076. X         } /* end if a -argument */
  1077. X     } else {    /* a filename - i guess */
  1078. X         if ( (arg - yydebug - cppflags - otherflags) == 1 )
  1079. X           infile = margv[arg];    
  1080. X         else if ( (arg - yydebug - cppflags - otherflags) == 2 )
  1081. X           outfile = margv[arg];
  1082. X         else
  1083. X           FatalError ("Usage: et [-d] [-q] [-%s] [infile [outfile]]", CPPARGS);
  1084. X     } /* end if a filename argument */
  1085. X     }    /* done with parsing all of the arguments */
  1086. X     if (otherflags)
  1087. X       FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
  1088. X     if (infile && strcmp(infile,"-") )
  1089. X       if (freopen (infile, "r", stdin) == NULL)
  1090. X     FatalError ("Cannot open input stream/file:", infile);
  1091. X     if (outfile && strcmp(outfile,"-") )
  1092. X       if (freopen (outfile, "w", stdout) == NULL)
  1093. X     FatalError ("Cannot open output stream/file:", outfile);
  1094. X     if (cppflags && cpp(margc,margv))
  1095. X     FatalError ("Cannot open preprocessor", CPP);
  1096. X    printf ("###################################################\n");
  1097. X    printf ("##                                               ##\n");
  1098. X    printf ("##  WARNING: THIS FILE IS THE OUTPUT OF THE      ##\n");
  1099. X    printf ("##           `EASE' PRECOMPILER FOR SENDMAIL     ##\n");
  1100. X    printf ("##           CONFIGURATION FILES.                ##\n");
  1101. X    printf ("##                                               ##\n");
  1102. X    printf ("##           MAKE MODIFICATIONS TO THE SOURCE    ##\n");
  1103. X    printf ("##           FILE ONLY.  CHANGES MADE DIRECTLY   ##\n");
  1104. X    printf ("##           TO THIS FILE WILL DISAPPEAR THE     ##\n");
  1105. X    printf ("##           NEXT TIME THAT EASE IS RUN.         ##\n");
  1106. X    printf ("##                                               ##\n");
  1107. X    printf ("##           $Revision: 3.2 $                    ##\n");
  1108. X    printf ("##                                               ##\n");
  1109. X    printf ("###################################################\n");
  1110. X}
  1111. X
  1112. X/* cpp preprocessor code
  1113. X * copied from Schreiner and Friedman's book:
  1114. X * Introduction to Compiler Construction with Unix
  1115. X *
  1116. X * Bruce Barnett
  1117. X */
  1118. X
  1119. int cpp(argc,argv)
  1120. X     int argc;
  1121. X     char **argv;
  1122. X{
  1123. X    char **argp, *cmd;
  1124. X    extern FILE *yyin;    /* for lex input */
  1125. X    extern FILE *popen();
  1126. X    int i;
  1127. X
  1128. X    for (i = 0, argp = argv; *++argp; )
  1129. X      if (**argp == '-' &&
  1130. X      index(CPPARGS, (*argp)[1]))
  1131. X    i+=strlen(*argp) + 1;
  1132. X    if ( ! (cmd = (char *) calloc(i + sizeof CPP, sizeof(char))))
  1133. X      return -1;    /* no room */
  1134. X    (void ) strcpy(cmd,CPP);
  1135. X    for (argp = argv; *++argp; )
  1136. X      if (**argp == '-' &&
  1137. X      index(CPPARGS, (*argp)[1]))
  1138. X    strcat(cmd, " "), strcat(cmd, *argp);
  1139. X    if (yyin = popen(cmd,"r"))
  1140. X      i = 0;    /* all's well */
  1141. X    else
  1142. X      i = -1;    /* no preprocessor */
  1143. X    cfree(cmd);
  1144. X    return i;
  1145. X}
  1146. END_OF_FILE
  1147. if test 7952 -ne `wc -c <'src/main.c'`; then
  1148.     echo shar: \"'src/main.c'\" unpacked with wrong size!
  1149. fi
  1150. # end of 'src/main.c'
  1151. fi
  1152. if test -f 'src/strops.c' -a "${1}" != "-c" ; then 
  1153.   echo shar: Will not clobber existing file \"'src/strops.c'\"
  1154. else
  1155. echo shar: Extracting \"'src/strops.c'\" \(17077 characters\)
  1156. sed "s/^X//" >'src/strops.c' <<'END_OF_FILE'
  1157. X#ifdef FLUKE
  1158. X# ifndef LINT
  1159. X    static char RCSid[] = "@(#)FLUKE  $Header: /home/kreskin/u0/barnett/Src/Ease/ease/src/RCS/strops.c,v 3.4 1991/10/15 17:02:04 barnett Exp $";
  1160. X# endif LINT
  1161. X#endif FLUKE
  1162. X
  1163. X/*
  1164. X *    strops.c   -- Contains string operation routines used for constructing
  1165. X *              definitions in cf format.
  1166. X *
  1167. X *    author       -- James S. Schoner, Purdue University Computing Center,
  1168. X *                        West Lafayette, Indiana  47907
  1169. X *
  1170. X *    date       -- July 9, 1985
  1171. X *
  1172. X *    Copyright (c) 1985 by Purdue Research Foundation
  1173. X *
  1174. X *    All rights reserved.
  1175. X *
  1176. X * $Log: strops.c,v $
  1177. X * Revision 3.4  1991/10/15  17:02:04  barnett
  1178. X * Detect if (one_or_more) next ($2) error
  1179. X *
  1180. X * Revision 3.3  1991/09/09  16:33:23  barnett
  1181. X * Minor bug fix release
  1182. X *
  1183. X * Revision 3.2  1991/05/16  10:45:25  barnett
  1184. X * Better support for System V machines
  1185. X * Support for machines with read only text segments
  1186. X *
  1187. X * Revision 3.1  1991/02/25  22:09:52  barnett
  1188. X * Fixed some portability problems
  1189. X *
  1190. X * Revision 3.0  1991/02/22  18:50:27  barnett
  1191. X * Added support for HP/UX and IDA sendmail.
  1192. X *
  1193. X * Revision 2.1  1990/01/30  15:52:55  jeff
  1194. X * Added SunOS/Ultrix/IDA extensions  Jan 24, 1989 Bruce Barnett
  1195. X *
  1196. X * Revision 2.0  88/06/15  14:42:55  root
  1197. X * Baseline release for net posting. ADR.
  1198. X */
  1199. X
  1200. X#include "fixstrings.h"
  1201. X#include <stdio.h>
  1202. X#include <strings.h>
  1203. X#include <ctype.h>
  1204. X#include "symtab.h"
  1205. X
  1206. X#define MAXTOKPOS   99        /* maximum number of token positions */
  1207. X#define MAXNAME        1024    /* maximum length of an identifier   */
  1208. X
  1209. extern struct he *LookupSymbol ();
  1210. extern char       MakeMac ();
  1211. extern void      FatalError (),
  1212. X          PrintError (),
  1213. X          ErrorReport ();
  1214. extern char *      malloc ();
  1215. X
  1216. short  Rformat = FALSE;            /* class read format flag      */
  1217. short number_of_fields = 0;        /* number of fields on this line */
  1218. X#ifdef    DATA_RW
  1219. static char   *Ptok   = "$  ";        /* positional token structure     */
  1220. static char   *Cfield = "$= ";        /* class reference structure      */
  1221. X#else
  1222. static char   *Ptok   = NULL;        /* positional token structure     */
  1223. static char   *Cfield = NULL;        /* class reference structure      */
  1224. X#endif
  1225. static char   *Ofield = "$-";        /* one token match structure      */
  1226. static char   *Zfield = "$*";        /* zero or more tokens structure  */
  1227. static char   *Pfield = "$+";        /* one or more tokens structure      */
  1228. X
  1229. X/*
  1230. X *  FLUKE jps 25-apr-86
  1231. X *
  1232. X *  Add the three new $%x, $%y, and $!x match operators that Sun introduced
  1233. X *  with release 3.0.
  1234. X */
  1235. X
  1236. X#ifdef    DATA_RW
  1237. static char   *Mfield = "$% ";        /*    match in specified YP map */
  1238. static char   *Nfield = "$! ";        /* no match in specified YP map */
  1239. static char   *Mtest  = "$? ";        /* conditional macro test string  */
  1240. X#else
  1241. static char   *Mfield = NULL;        /*    match in specified YP map */
  1242. static char   *Nfield = NULL;        /* no match in specified YP map */
  1243. static char   *Mtest  = NULL;        /* conditional macro test string  */
  1244. X#endif
  1245. X
  1246. X#ifndef    DATA_RW
  1247. X/* This section of code is for those machines with split text and data
  1248. X * areas - where string constants are not modifiable
  1249. X */
  1250. X#define nil (char *)0
  1251. X
  1252. char *      Strdup(string) /* a clone of the strdup() routine */
  1253. char    *string;
  1254. X{
  1255. X    char *s;
  1256. X    s=malloc(strlen(string));
  1257. X    if (!s) return (nil);
  1258. X    (void) sprintf(s,"%s",string);
  1259. X    return (s);
  1260. X}
  1261. void InitStrOps()
  1262. X{
  1263. X    if(!(Ptok = Strdup("$  ")) || !(Cfield = Strdup("$= ")) ||
  1264. X       !(Mfield = Strdup("$% ")) || !(Nfield = Strdup("$! ")) ||
  1265. X       !(Mtest = Strdup("$? ")))
  1266. X           FatalError("Out of memory in InitStrOps()", (char *)NULL);
  1267. X}
  1268. X#endif
  1269. X
  1270. X
  1271. X/*
  1272. X *    ConvOpt () -- Convert an Ease option identifier (optid) by returning a
  1273. X *              string representation of the cf format.  
  1274. X *
  1275. X */
  1276. char *
  1277. ConvOpt (optid) 
  1278. register enum opts optid;
  1279. X{
  1280. X    switch (optid) {
  1281. X        case opt_A  :    return ("A");
  1282. X        case opt_a  :    return ("a");
  1283. X        case opt_B  :    return ("B");
  1284. X        case opt_b  :    return ("b");
  1285. X        case d_opt_b:    return ("b");
  1286. X        case opt_C  :    return ("C");
  1287. X        case opt_c  :    return ("c");
  1288. X        case opt_D  :    return ("D");
  1289. X        case opt_d  :    return ("d");
  1290. X        case opt_e  :
  1291. X        case e_opt_e:    return ("e");
  1292. X        case opt_F  :    return ("F");
  1293. X        case opt_f  :    return ("f");
  1294. X        case opt_g  :    return ("g");
  1295. X        case opt_h  :    return ("h");    /* SunOS Maxhops */
  1296. X        case opt_H  :    return ("H");
  1297. X        case opt_I  :   return ("I");    /* HP/UX */
  1298. X        case opt_i  :
  1299. X        case d_opt_i:    return ("i");
  1300. X        case opt_L  :    return ("L");
  1301. X        case opt_m  :
  1302. X        case e_opt_m:    return ("m");
  1303. X        case opt_N  :    return ("N");
  1304. X        case opt_n  :    return ("n");
  1305. X        case opt_o  :    return ("o");
  1306. X        case opt_P  :    return ("P");
  1307. X        case e_opt_p:    return ("p");
  1308. X        case opt_Q  :    return ("Q");
  1309. X        case opt_q  :    return ("q");
  1310. X        case d_opt_q:    return ("q");
  1311. X        case opt_r  :    return ("r");
  1312. X        case opt_R  :    return ("R");
  1313. X        case opt_S  :    return ("S");
  1314. X        case opt_s  :    return ("s");
  1315. X        case opt_T  :    return ("T");
  1316. X        case opt_t  :    return ("t");
  1317. X        case opt_u  :    return ("u");
  1318. X        case opt_v  :    return ("v");
  1319. X        case opt_W  :    return ("W");
  1320. X        case e_opt_w:    return ("w");
  1321. X        case opt_x  :    return ("x");
  1322. X        case opt_X  :    return ("X");
  1323. X        case opt_y  :    return ("y");
  1324. X        case opt_Y  :    return ("Y");
  1325. X        case opt_z  :    return ("z");
  1326. X        case opt_Z  :    return ("Z");
  1327. X        case e_opt_z:    return ("z");
  1328. X        case opt_SL  :    return ("/");
  1329. X        default     :    FatalError ("Bad case in ConvOpt ()", (char *) NULL);
  1330. X    }
  1331. X    /*NOTREACHED*/
  1332. X}
  1333. X
  1334. X
  1335. X/*
  1336. X *    ConvFlg () -- Convert an Ease mailer flag identifier (flgid) by 
  1337. X *              string representation of the cf format.  
  1338. X *
  1339. X */
  1340. char *
  1341. ConvFlg (flgid)
  1342. register enum flgs flgid;    /* flag identifier */
  1343. X{
  1344. X    switch (flgid) {
  1345. X        case flg_f:    return ("f");
  1346. X        case flg_r:    return ("r");
  1347. X        case flg_S:    return ("S");
  1348. X        case flg_n:    return ("n");
  1349. X        case flg_l:    return ("l");
  1350. X        case flg_s:    return ("s");
  1351. X        case flg_m:    return ("m");
  1352. X        case flg_F:    return ("F");
  1353. X        case flg_D:    return ("D");
  1354. X        case flg_M:    return ("M");
  1355. X        case flg_x:    return ("x");
  1356. X        case flg_P:    return ("P");
  1357. X        case flg_u:    return ("u");
  1358. X        case flg_h:    return ("h");
  1359. X        case flg_H:    return ("H");
  1360. X        case flg_A:    return ("A");
  1361. X        case flg_U:    return ("U");
  1362. X        case flg_e:    return ("e");
  1363. X        case flg_X:    return ("X");
  1364. X        case flg_L:    return ("L");
  1365. X        case flg_p:    return ("p");
  1366. X        case flg_I:    return ("I");
  1367. X        case flg_C:    return ("C");
  1368. X        case flg_E:    return ("E");
  1369. X        case flg_R:    return ("R");
  1370. X        case flg_V:    return ("V");    /* IDA */
  1371. X        case flg_B:    return ("B");    /* IDA */
  1372. X        default   :    FatalError ("Bad case in ConvFlg ()", (char *) NULL);
  1373. X    }
  1374. X    /*NOTREACHED*/
  1375. X}
  1376. X
  1377. X
  1378. X/*
  1379. X *    ConvMat () -- Convert an Ease mailer attribute (mat) by returning a
  1380. X *              string representation of the cf format.  
  1381. X *
  1382. X */
  1383. char *
  1384. ConvMat (mat)
  1385. register enum mats mat;        /* mailer attribute flag */
  1386. X{
  1387. X    switch (mat) {
  1388. X        case mat_path        : return ("P");
  1389. X        case mat_flags        : return ("F");
  1390. X        case mat_sender        : return ("S");
  1391. X        case mat_recipient    : return ("R");
  1392. X        case mat_argv        : return ("A");
  1393. X        case mat_eol        : return ("E");
  1394. X        case mat_maxsize    : return ("M");
  1395. X        default            : FatalError ("Bad case in ConvMat ()", (char *) NULL);
  1396. X    }
  1397. X    /*NOTREACHED*/
  1398. X}
  1399. X
  1400. X
  1401. X/*
  1402. X *    MacScan () -- Scan a string (pstring) for macros, replacing the Ease
  1403. X *              form with the one-character form required by cf format.
  1404. X *
  1405. X */
  1406. char *
  1407. MacScan (pstring)
  1408. char *pstring;        /* macro expandable string */
  1409. X{
  1410. X    register char *searchptr;    /* string search pointer     */
  1411. X    register char *bptr, *eptr;    /* macro begin and end pointers */
  1412. X    char macname [MAXNAME];        /* macro name buffer        */
  1413. X    int    quote = 0;            /* flag for detecting a quote() function */
  1414. X
  1415. X    if ((searchptr = pstring) == NULL)
  1416. X        return ((char *) NULL);
  1417. X    while (*searchptr != '\0')     /* find and rewrite all macros  */
  1418. X        if (*searchptr == '\\') {
  1419. X            searchptr = searchptr + 2;
  1420. X            continue;
  1421. X        } else if (*searchptr++ == '$') {
  1422. X            if (*searchptr == '{') {
  1423. X            if (sscanf (searchptr + 1, "quote(%[^)])", macname) == 1) {
  1424. X                /* a quote(macro) sequence */
  1425. X                    quote++;
  1426. X            } else if (sscanf (searchptr + 1, "%[^}]", macname) != 1) {
  1427. X                PrintError ("Invalid macro format: %s", searchptr + 1);
  1428. X                return ((char *) NULL);
  1429. X            } 
  1430. X            if (quote) {
  1431. X                quote=0;
  1432. X                *searchptr++='!'; /* insert a quote */
  1433. X                /* insert the macro letter */
  1434. X                *searchptr++ = MakeMac (LookupSymbol (macname),
  1435. X                            (unsigned) ID_MACRO);
  1436. X                /* now looking at quote(   */
  1437. X                /* must skip over everything until )}, and then rewrite
  1438. X                   the rest of the macro */
  1439. X                bptr = eptr = searchptr; 
  1440. X                while (*eptr && *eptr != ')') /* skip to quote */
  1441. X                  eptr++;
  1442. X                while (*eptr && *eptr != '}') /* skip past } */
  1443. X                  eptr++;
  1444. X                eptr++;
  1445. X                do    /* copy everything from eptr to end of line */
  1446. X                  *bptr++ = *eptr;
  1447. X                while (*eptr++ != '\0');
  1448. X            } else {
  1449. X                *searchptr++ = MakeMac (LookupSymbol (macname),
  1450. X                            (unsigned) ID_MACRO);
  1451. X                bptr = eptr = searchptr;
  1452. X                while (*eptr++ != '}')    /* delete until end of {name} */
  1453. X                  /* empty */ ;
  1454. X                do    /* copy rest of line */
  1455. X                  *bptr++ = *eptr;
  1456. X                while (*eptr++ != '\0');
  1457. X            }
  1458. X            } else if (isupper(*searchptr)){ /* $ not followed by { */
  1459. X            /* macro name might be one character */
  1460. X            /* but or might be more than one.    */
  1461. X            if (sscanf (searchptr, "%[A-Z]", macname) != 1) {
  1462. X                PrintError ("Invalid macro format: %s", searchptr + 1);
  1463. X                return ((char *) NULL);
  1464. X            } 
  1465. X            *searchptr++ = MakeMac (LookupSymbol (macname),
  1466. X                        (unsigned) ID_MACRO);
  1467. X            bptr = eptr = searchptr;
  1468. X            while (isupper(*eptr))    /* delete old macro chars */
  1469. X                eptr++;
  1470. X            do
  1471. X                *bptr++ = *eptr;
  1472. X            while (*eptr++ != '\0');
  1473. X            } 
  1474. X        } /* end of (if char == '$' ) */
  1475. X    return (pstring);
  1476. X}
  1477. X
  1478. X
  1479. X/*
  1480. X *    MakeRStr () -- Construct and return a pointer to a class read string 
  1481. X *               using the filename fname and read format rformat.  
  1482. X *
  1483. X */
  1484. char *
  1485. MakeRStr (fname, rformat)
  1486. char *fname,            /* file name for class read */
  1487. X     *rformat;            /* format for class read    */
  1488. X{
  1489. X    register char *res;    /* resultant read string    */
  1490. X
  1491. X    Rformat = TRUE;        /* set read format flag     */
  1492. X    if (rformat == NULL)
  1493. X        return (fname);
  1494. X    res = (char *) realloc (fname, strlen (fname) + strlen (rformat) + 2);
  1495. X    if (res == NULL)
  1496. X        FatalError ("System out of string space in MakeRStr ()", (char *) NULL);
  1497. X    res = strcat (res, " ");    /* construct read string */
  1498. X    res = strcat (res, rformat);
  1499. X    free (rformat);
  1500. X    return (res);
  1501. X}
  1502. X
  1503. X
  1504. X/*
  1505. X *    ListAppend () -- Append string list2 to string list1 using the 
  1506. X *             separator sep.  A pointer to the newly constructed
  1507. X *             string is returned.
  1508. X *
  1509. X */
  1510. char *
  1511. ListAppend (list1, list2, sep)
  1512. char *list1,            /* first string     */
  1513. X     *list2,            /* second string      */
  1514. X     *sep;            /* string separator    */
  1515. X{
  1516. X    register char *res;    /* resultant string    */
  1517. X
  1518. X    res = (char *) malloc (strlen (list1) + strlen (list2) + strlen (sep) + 1);
  1519. X    if (res == NULL)
  1520. X        FatalError ("System out of string space in ListAppend ()", (char *) NULL);
  1521. X    res = strcpy (res, list1);
  1522. X    if (list1 != NULL)    /* use separator if first string not null */
  1523. X        res = strcat (res, sep);
  1524. X    res = strcat (res, list2);
  1525. X    return (res);
  1526. X}
  1527. X
  1528. X
  1529. X/*
  1530. X *    MakeCond () -- Construct a macro conditional string in cf format.  The
  1531. X *               conditional is based on the macro testmac, with an "if
  1532. X *               set" result ifstring, which may contain an optional 
  1533. X *               "if not set" result string appended to it.
  1534. X *
  1535. X */
  1536. char *
  1537. MakeCond (testmac, ifstring)
  1538. struct he *testmac;        /* macro for conditional testing          */
  1539. char       *ifstring;         /* "if macro set" result string(s)           */
  1540. X{
  1541. X    register char *res;    /* resultant conditional string             */
  1542. X
  1543. X    Mtest[2] = MakeMac (testmac, (unsigned) ID_MACRO); /* get one-char macro rep */
  1544. X    res = (char *) malloc (strlen (ifstring) + 6);
  1545. X    if (res == NULL)
  1546. X        FatalError ("System out of string space in MakeCond ()", (char *) NULL);
  1547. X    res = strcpy (res, Mtest);
  1548. X    res = strcat (res, ifstring);        /* build result part      */
  1549. X    res = strcat (res, "$.");        /* end of conditional     */
  1550. X    free (ifstring);
  1551. X    return (res);
  1552. X}
  1553. X
  1554. X
  1555. X/*
  1556. X *    MakePosTok () -- Construct and return a positional token string 
  1557. X *             representation from the parameter num.
  1558. X *
  1559. X */
  1560. char *
  1561. MakePosTok (num)
  1562. register int num;            /* numerical value of positional token */
  1563. X{
  1564. X    char buf[100];
  1565. X    if (num > MAXTOKPOS) {
  1566. X        ErrorReport ("Positional token too large.\n");
  1567. X        return ((char *) NULL);
  1568. X    } else {
  1569. X        if (num > number_of_fields) {
  1570. X        sprintf(buf," $%d used in right hand side of rule, but maximum positional parameter is %d\n", num, number_of_fields);
  1571. X        ErrorReport(buf);
  1572. X        }
  1573. X        if (num > 9) {    /* two-digit positional token */
  1574. X            Ptok[1] = '0' + (num / 10);
  1575. X            Ptok[2] = '0' + (num % 10);
  1576. X            Ptok[3] = '\0';
  1577. X        } else {
  1578. X            Ptok[1] = '0' + num;
  1579. X            Ptok[2] = '\0';
  1580. X        }
  1581. X    return (Ptok);
  1582. X    }
  1583. X}
  1584. X
  1585. X
  1586. X/*
  1587. X *    Bracket () -- Construct and return a cf string form of the 
  1588. X *              canonicalization of the string identifier passed in
  1589. X *              the string parameter psb if dflag is true, else
  1590. X *              simply bracket the identifier without dollar signs
  1591. X *              for numeric hostname specifications.
  1592. X *
  1593. X */
  1594. char *
  1595. Bracket (psb, dflag)
  1596. char *psb;            /* identifier to be canonicalized */
  1597. short dflag;            /* dollar flag               */
  1598. X{
  1599. X    register char *res;    /* resultant cf form           */
  1600. X    register short extra;    /* extra space needed for malloc  */
  1601. X    
  1602. X    extra = dflag ? 5 : 3;
  1603. X    res = (char *) malloc (strlen (psb) + extra);
  1604. X    if (res == NULL)
  1605. X        FatalError ("System out of string space in Bracket ()", (char *) NULL);
  1606. X    if (dflag)
  1607. X        res = strcpy (res, "$[");
  1608. X    else
  1609. X        res = strcpy (res, "[");
  1610. X    res = strcat (res, psb);
  1611. X    if (dflag)
  1612. X        res = strcat (res, "$");
  1613. X    res = strcat (res, "]");
  1614. X    return (res);
  1615. X}
  1616. X/*
  1617. X *    DbmParen () -- Construct and return a cf string form of the 
  1618. X *              dbm reference of the IDA database identifier passed in
  1619. X *              the string parameter db_psb, looking up the string identifier
  1620. X *              passed in the string parameter lup_psb.
  1621. X *
  1622. X */
  1623. char *
  1624. DbmParen (db_psb, lup_psb)
  1625. char *db_psb;            /* identifier of data base */
  1626. char *lup_psb;            /* identifier being looked up */
  1627. X{
  1628. X    register char *res;    /* resultant cf form           */
  1629. X    
  1630. X    res = (char *) malloc (strlen (lup_psb) + 7);
  1631. X    if (res == NULL)
  1632. X        FatalError ("System out of string space in DbmParen ()", (char *) NULL);
  1633. X    res = strcpy (res, "$(x ");
  1634. X    *(res+2) = *db_psb;
  1635. X    res = strcat (res, lup_psb);
  1636. X    res = strcat (res, " $)");
  1637. X    return (res);
  1638. X}
  1639. X
  1640. X
  1641. X/*
  1642. X *    MakeRSCall () -- Construct and return a cf string form of a call
  1643. X *             to a ruleset (cid), which would pass to it the
  1644. X *             remainder of a rewriting address (rwaddr).
  1645. X *
  1646. X */
  1647. char *
  1648. MakeRSCall (cid, rwaddr)
  1649. register struct he *cid;    /* called ruleset identifier         */
  1650. register char *rwaddr;        /* remainder of rewriting address    */
  1651. X{
  1652. X    register char *res;    /* resultant cf string for the call  */
  1653. X    
  1654. X    if (!ISRULESET(cid->idtype)) {    /* check validity of ruleset */
  1655. X        PrintError ("Undefined ruleset identifier: %s", cid->psb);
  1656. X        return ((char *) NULL);
  1657. X    }
  1658. X    /*
  1659. X     * FLUKE jps - 8-may-86 - boost string size by 1 to accomodate space
  1660. X     * character.
  1661. X     */
  1662. X    res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 4);
  1663. X    if (res == NULL)
  1664. X        FatalError ("System out of string space in MakeRSCall ()", (char *) NULL);
  1665. X    res = strcpy (res, "$>");    /* construct the call string */
  1666. X    res = strcat (res, cid->idval.rsn);
  1667. X    res = strcat (res, " ");  /* FLUKE jps - work around sendmail bug:
  1668. X                   * whitespace is needed to separate tokens:
  1669. X                   * for example:  $>30$D will confuse
  1670. X                   * sendmail, but $>30 $D is OK.
  1671. X                   */
  1672. X    res = strcat (res, rwaddr);
  1673. X    return (res);
  1674. X}
  1675. X
  1676. X
  1677. X/*
  1678. X *    MakeField () -- Construct and return the cf string format for a
  1679. X *            field variable.  The match count (count), an optional
  1680. X *            class (class), and a match repetition flag (fstar)
  1681. X *            are used to determine what type of field string to
  1682. X *            construct.
  1683. X *
  1684. X *  FLUKE jps 25-apr-86 - Modified to add a fourth parameter "isYPmap".  This
  1685. X *  supports Sun's new Yellow Pages match patterns added in release 3.0.
  1686. X *
  1687. X */
  1688. char *
  1689. X    MakeField (count, class, fstar, isYPmap)
  1690. register int count;        /* match count (0 or 1) */
  1691. register struct he *class;    /* optional class type  */
  1692. register short fstar;        /* repetition flag    */
  1693. register short isYPmap;        /* "class" name is really a YP map name */
  1694. X{
  1695. X    switch (count) {
  1696. X        case 0:      if (class == NULL)    /* any token is valid */
  1697. X                if (fstar)
  1698. X                    return (Zfield);
  1699. X                else {
  1700. X                    ErrorReport ("Invalid field type.\n");
  1701. X                    return ((char *) NULL);
  1702. X                }
  1703. X              else {        /* match 0 from class or map */
  1704. X                if (isYPmap) {
  1705. X                    /*  "class" is a misnomer here; it's really
  1706. X                     *  a simple macro name for a YP map.
  1707. X                     *  FLUKE jps 25-apr-86
  1708. X                     */
  1709. X                    Nfield[2] = MakeMac (class, (unsigned) ID_MACRO);
  1710. X                    return (Nfield);
  1711. X                } else {
  1712. X                Cfield[1] = '~';
  1713. X                Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
  1714. X                return (Cfield);
  1715. X              }
  1716. X              }
  1717. X        case 1:      if (class == NULL)    /* any token is valid */
  1718. X                if (fstar)
  1719. X                    return (Pfield);
  1720. X                else
  1721. X                    return (Ofield);
  1722. X              else {        /* match 1 from class or map */
  1723. X                if (isYPmap) {
  1724. X                    /*  "class" is a misnomer here; it's really
  1725. X                     *  a simple macro name for a YP map.
  1726. X                     *  FLUKE jps 25-apr-86
  1727. X                     */
  1728. X                    Mfield[2] = MakeMac (class, (unsigned) ID_MACRO);
  1729. X                    return (Mfield);
  1730. X                } else {
  1731. X                Cfield[1] = '=';
  1732. X                Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
  1733. X                return (Cfield);
  1734. X                }
  1735. X              }
  1736. X        default:  ErrorReport ("Invalid field type.\n");
  1737. X    }
  1738. X    /*NOTREACHED*/
  1739. X}
  1740. END_OF_FILE
  1741. if test 17077 -ne `wc -c <'src/strops.c'`; then
  1742.     echo shar: \"'src/strops.c'\" unpacked with wrong size!
  1743. fi
  1744. # end of 'src/strops.c'
  1745. fi
  1746. echo shar: End of archive 3 \(of 6\).
  1747. cp /dev/null ark3isdone
  1748. MISSING=""
  1749. for I in 1 2 3 4 5 6 ; do
  1750.     if test ! -f ark${I}isdone ; then
  1751.     MISSING="${MISSING} ${I}"
  1752.     fi
  1753. done
  1754. if test "${MISSING}" = "" ; then
  1755.     echo You have unpacked all 6 archives.
  1756.     rm -f ark[1-9]isdone
  1757. else
  1758.     echo You still need to unpack the following archives:
  1759.     echo "        " ${MISSING}
  1760. fi
  1761. ##  End of shell archive.
  1762. exit 0
  1763.